import { Service, IArticleWhere, IUpdateResult, IArticle } from 'egg';
import * as fs from 'fs';
const fsPromise = require('fs').promises;
import * as path from 'path';
/**
 * Test Service
 */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// enum ArticleColumn {
//   'id', 'title', 'author', 'category_id', 'alias', 'pubdate', 'abstract', 'clicks', 'is_hidden', 'content'
// }
// interface IArticleWhere {alias?: string, author?: string, is_hidden?: number}
const articleInfoColumns_Hidden = [ 'id', 'title', 'author', 'category_id', 'alias', 'pubdate', 'abstract', 'clicks' ];
export default class Articles extends Service {
  mysql = this.app.mysql as any;
  /**
   * getInfo
   * @param limit - 单页分页数量
   * @param offset - 偏移行数
   * ? @param columns - 字段名，默认获取除了内容外的所有字段
   * ? @param where - 限定条件
   * ? @param order - 排序，默认为按点击量排序: clicks，可选发布时间: pubdate
   * ? @param reverse - 是否为增序排列 true，默认为降序 false
   * ? @param showHidden - 显示隐藏的文章
   */
  public async getInfo(limit:number, offset:number, columns = articleInfoColumns_Hidden, where:IArticleWhere = {}, order = 'id', reverse = 1, showHidden = false) {
    const mysql = this.app.mysql as any;
    // select columns 字段名
    const queryColumns = [ ...columns ];
    if (showHidden) {
      queryColumns.push('is_hidden');
    } else {
      where.is_hidden = 0;
    }
    // Order by [[字段名，'ASC'||'DESC']]
    if (!articleInfoColumns_Hidden.includes(order)) {
      console.log({order});
      order = 'id';
    }
    let whereArray = [];
    let whereArrayValues = [];
    const regexpColumns = ['alias','title','author'];
    for (const key of Object.keys(where)){
      if (regexpColumns.includes(key)) whereArray.push(key + ' REGEXP ?');
      else whereArray.push(key + ' =? ');
      whereArrayValues.push(where[key]);
    }
    // select ... from tablename where ... and ... limit offset, pagesize
    let sql_columns = `select ${queryColumns.join(',')} from articles_categories where ${whereArray.length>0 ? whereArray.join(' AND ') :'1'} Order by \`${order}\` ${reverse? 'DESC' : 'ASC'} limit ?, ?;`;
    let sql_count = `select COUNT(1) as count from articles_categories where ${whereArray.length>0 ? whereArray.join(' AND ') :'1'}`;
    const total = (await mysql.query(sql_count, whereArrayValues))[0].count;
    console.log('select articles at sql: ', sql_columns);
    // Result ROWS
    const result = await mysql.query(sql_columns, [...whereArrayValues, offset, limit]);

    // const result = await mysql.select('articles_categories', {
    //   where,
    //   columns: queryColumns,
    //   orders: orders.length > 0 ? orders : undefined,
    //   limit,
    //   offset,
    // });
    return {
      total,
      article_infos: result,
    };
  }
  /**
   * getById 通过ID获取文章主体内容
   * @param id - article.id
   * ? @param hasInfo - 是否包含文章其他信息，默认不包含 false
   * ? @param showHidden - 显示隐藏的文章，默认不显示 false
   */
  public async getById(id:number, hasInfo = false, showHidden = false) {
    
    // select columns 字段名
    const queryColumns:string[] = [ 'content' ];
    const where:IArticleWhere = {};
    if (hasInfo) {
      queryColumns.push(...articleInfoColumns_Hidden);
    }
    if (showHidden) {
      queryColumns.push('is_hidden');
    } else {
      where.id = id;
      where.is_hidden = 0;
    }
    // Result ROWS
    const articles = await this.mysql.select('articles_categories', {
      where,
      columns: queryColumns,
      limit: 1,
      offset: 0,
    });
    return articles.length > 0 ? articles[0] : undefined;
  }
  public async deleteById(id:number) {
     let result:IUpdateResult = await this.mysql.delete('articles', {
       id
     });
    //  未删除
     if (result.affectedRows <=0) {
       return false;
     }
    //  成功删除
    try {
      const filepath = path.join(this.config.filePath.articles, id.toString());
      if (fs.existsSync(filepath)){
        await fsPromise.rmdir(filepath, {
          recursive: true,
        });
      }
      return true;
    } catch (error) {
      throw error;
    }
  }
  public async create(article: IArticle){
    this.ctx.helper.deleteUndefined(article);
    try {
      let result:IUpdateResult = await this.mysql.insert('articles', article);  
      if (result.affectedRows>0) {
        return result.insertId;
      }else {
        return undefined;
      }
    } catch (error) {
      return undefined;
    }

  }
  public async updateById(id: number, title?:string, author?:string, category_id?:number, abstract?: string, content?:string, is_hidden?:number, pubdate?:string){
    const article:any = {
      id,
      title,
      author,
      category_id,
      abstract,
      content,
      is_hidden,
      pubdate,
    }
    this.ctx.helper.deleteUndefined(article);
    try {
      let result:IUpdateResult = await this.mysql.update('articles', article);  
      
      if (result.affectedRows>0) {
        return result.message;
      }else {
        return undefined;
      }
    } catch (error) {
      return undefined;
    }

  }

}
